﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;


namespace TireSizesCalculator.Model
{
    public class TireSize
    {
        private readonly static Regex SIZE_REGEX = new Regex(@"\s*(\d{3})\s*/\s*(\d{2})\s*R\s*(\d{2})\s*", RegexOptions.Singleline | RegexOptions.IgnoreCase);
        private readonly static String TIRE_SIZE_FORMAT = @"{0}/{1}R{2}";
        private int _width;
        private int _profile;
        private int _radius;
        private double _radiusInMiliMeters;
        private double _wheelSize;


        /// <summary>
        /// Konstruktor
        /// </summary>
        /// <param name="size">Wielkość koła w formacie "<szerokość>/<profil>R<średnica_felgi>"</param>
        public TireSize(String size)
        {
            SetSize(size);
        }

        /// <summary>
        /// Konstruktor
        /// </summary>
        /// <param name="width">Szerokość opony</param>
        /// <param name="profile">Profil opony</param>
        /// <param name="radius">Średnica felgi</param>
        public TireSize(int width, int profile, int radius)
        {
            SetSize(width, profile, radius);
        }


        /// <summary>
        /// Średnica felgi wyrażona w calach
        /// </summary>
        public int Radius
        {
            get
            {
                return _radius;
            }
        }

        /// <summary>
        /// Średnica felgi wyrażona w milimetrach
        /// </summary>
        public double RadiusInMiliMeters
        {
            get
            {
                return _radiusInMiliMeters;
            }
        }

        /// <summary>
        /// Szerokość opony wyrażona w milimetrach
        /// </summary>
        public int Width
        {
            get
            {
                return _width;
            }
        }

        /// <summary>
        /// Jest to (wysokość / szerokość) * 100 wyrażona w procentach
        /// </summary>
        public int Profile
        {
            get
            {
                return _profile;
            }
        }

        /// <summary>
        /// Całkowita wielkość koła wyrażona w milimetrach
        /// </summary>
        public double WheelSize
        {
            get
            {
                return _wheelSize;
            }
        }

        /// <summary>
        /// Wyrażenie regularne wykrywające zapis rozmiaru opony
        /// </summary>
        public static Regex SizeFormatRegex
        {
            get
            {
                return SIZE_REGEX;
            }
        }


        /// <summary>
        /// Ustawienie wielkości koła
        /// </summary>
        /// <param name="width">Szerokość opony</param>
        /// <param name="profile">Profil opony</param>
        /// <param name="radius">Średnica felgi</param>
        private void SetSize(int width, int profile, int radius)
        {
            _width = width;
            _profile = profile;
            _radius = radius;
            _radiusInMiliMeters = CalculateInchToMiliMeters(_radius);
            _wheelSize = CalculateWheelSize();
        }

        /// <summary>
        /// Ustawienie wielkości koła przy pomocy zapisu w formacie "<szerokość>/<profil>R<średnica_felgi>"
        /// </summary>
        /// <param name="size"></param>
        private void SetSize(String size)
        {
            Match match = SIZE_REGEX.Match(size);

            if (match.Success)
            {
                _width = Int32.Parse(match.Groups[1].Value);
                _profile = Int32.Parse(match.Groups[2].Value);
                _radius = Int32.Parse(match.Groups[3].Value);
                _radiusInMiliMeters = CalculateInchToMiliMeters(_radius);
                _wheelSize = CalculateWheelSize();
            }
            else
            {
                throw new FormatException("Format wprowadzonych danych jest nieprawidłowy.");
            }
        }

        public override string ToString()
        {
            return String.Format(TIRE_SIZE_FORMAT, _width, _profile, _radius);
        }

        public override bool Equals(Object obj)
        {
            if (obj is TireSize)
            {
                TireSize size = obj as TireSize;
                return (_width == size.Width) && (_profile == size.Profile) && (_radius == size.Radius);
            }
            else
            {
                return base.Equals(obj);
            }
        }


        /// <summary>
        /// Przeliczenie wartości w calach na milimetry
        /// </summary>
        /// <param name="value">Wartość wyrażona w calach</param>
        /// <returns>Wartość wyrażona w milimetrach</returns>
        private double CalculateInchToMiliMeters(int value)
        {
            return value * 25.4d;       // 1" == 2.54 cm && 1cm == 10mm => 1" == 254mm
        }

        /// <summary>
        /// Wyliczenie całkowitej średnicy koła wyrażonej w milimetrach
        /// </summary>
        /// <returns>Całkowita średnica koła wyrażona w milimetrach</returns>
        private double CalculateWheelSize()
        {
            return _radiusInMiliMeters + 2 * _width * (_profile / 100d);
        }

    }
}
